#include "Game.h"

#include "CSGD_Direct3D.h"
#include "CSGD_DirectInput.h"
#include "CSGD_TextureManager.h"
#include "CSGD_XAudio2.h"

#include "TitleMenuState.h"
#include "OptionsMenuState.h"
#include "SinglePlayerState.h"
#include "PauseMenuState.h"
#include "MainMenuState.h"
#include "Economy.h"

#include "AnimationSystem.h"
#include "EntityManager.h"
#include "ParticleManager.h"
#include "LevelManager.h"
#include "BitmapFont.h"
#include "LevelManager.h"

#include "Message.h"
#include "MessageSystem.h"
#include <vector>
#include <ctime>

CGame* CGame::s_pInstance = nullptr;


CGame* CGame::GetInstance( void )
{
	if( s_pInstance == nullptr )
		s_pInstance = new CGame;

	return s_pInstance;
}

void CGame::DeleteInstance( void )
{
	delete s_pInstance;
	s_pInstance = nullptr;
}


CGame::CGame( void )
{
	m_pD3D				= nullptr;
	m_pDI				= nullptr;
	m_pTM				= nullptr;
	m_pXA				= nullptr;
	m_pBF				= nullptr;
	m_pCurrState		= nullptr;
	m_pEntityManager	= nullptr;
	m_pParticleManager	= nullptr;
	m_pLM				= nullptr;
	
	m_nScreenWidth		= 1;
	m_nScreenHeight		= 1;
	m_bIsWindowed		= true;
	m_dwCurrTime		= 0;
	m_nSfxID			= -1;
	m_nBackgroundMusicID = -1;

	TestMessageThingBool = false;
	TestMessageThingTimer = 0.0f;
}

CGame::~CGame(void)
{
}

void CGame::Initialize( HWND hWnd, HINSTANCE hInstance,
					   int nWidth, int nHeight, bool bWindowed )
{
	srand((unsigned int)time(0));

	hGrabInstance = hInstance;

	m_pD3D			= CSGD_Direct3D::GetInstance();
	m_pDI			= CSGD_DirectInput::GetInstance();
	m_pTM			= CSGD_TextureManager::GetInstance();
	m_pXA			= CSGD_XAudio2::GetInstance();

	m_pEntityManager = CEntityManager::GetInstance();
	m_pParticleManager = CParticleManager::GetInstance();

	m_nScreenWidth	= nWidth;
	m_nScreenHeight	= nHeight;
	m_bIsWindowed	= bWindowed;

	m_pD3D->Initialize( hWnd, m_nScreenWidth, m_nScreenHeight, m_bIsWindowed, false );
	m_pDI->Initialize( hWnd, hInstance, DI_KEYBOARD | DI_JOYSTICKS  );
	m_pTM->Initialize( m_pD3D->GetDirect3DDevice(), m_pD3D->GetSprite() );
	m_pXA->Initialize();

	m_pBF = new CBitmapFont;
	m_pBF->Initialize();

	//Fix capital letter problems
	m_pBF->AddLetterDiff('A', 2);
	m_pBF->AddLetterDiff('B', 4);
	m_pBF->AddLetterDiff('C', 4);
	m_pBF->AddLetterDiff('D', 4);
	m_pBF->AddLetterDiff('E', 4);
	m_pBF->AddLetterDiff('F', 8);
	m_pBF->AddLetterDiff('G', -2);
	m_pBF->AddLetterDiff('H', 6);
	m_pBF->AddLetterDiff('I', 12);
	m_pBF->AddLetterDiff('J', 8);
	m_pBF->AddLetterDiff('K', 4);
	m_pBF->AddLetterDiff('L', 6);
	m_pBF->AddLetterDiff('N', 4);
	m_pBF->AddLetterDiff('P', 4);
	m_pBF->AddLetterDiff('R', 4);
	m_pBF->AddLetterDiff('S', 4);
	m_pBF->AddLetterDiff('T', 6);
	m_pBF->AddLetterDiff('U', 2);
	m_pBF->AddLetterDiff('V', 4);
	m_pBF->AddLetterDiff('W', -2);
	m_pBF->AddLetterDiff('X', 2);
	m_pBF->AddLetterDiff('Y', 4);
	m_pBF->AddLetterDiff('Z', 6);
	//Fix lower case letter problems
	m_pBF->AddLetterDiff('a', 2);
	m_pBF->AddLetterDiff('b', 4);
	m_pBF->AddLetterDiff('c', 6);
	m_pBF->AddLetterDiff('d', 4);
	m_pBF->AddLetterDiff('e', 4);
	m_pBF->AddLetterDiff('f', 8);
	m_pBF->AddLetterDiff('g', 2);
	m_pBF->AddLetterDiff('h', 6);
	m_pBF->AddLetterDiff('i', 12);
	m_pBF->AddLetterDiff('j', 8);
	m_pBF->AddLetterDiff('k', 4);
	m_pBF->AddLetterDiff('l', 10);
	m_pBF->AddLetterDiff('n', 6);
	m_pBF->AddLetterDiff('p', 4);
	m_pBF->AddLetterDiff('o', 2);
	m_pBF->AddLetterDiff('q', 2);
	m_pBF->AddLetterDiff('r', 10);
	m_pBF->AddLetterDiff('s', 4);
	m_pBF->AddLetterDiff('t', 8);
	m_pBF->AddLetterDiff('u', 4);
	m_pBF->AddLetterDiff('v', 4);
	m_pBF->AddLetterDiff('w', -2);
	m_pBF->AddLetterDiff('x', 6);
	m_pBF->AddLetterDiff('y', 4);
	m_pBF->AddLetterDiff('z', 6);
	//special characters
	m_pBF->AddLetterDiff('.', 10);
	m_pBF->AddLetterDiff(':', 10);

	m_nBackgroundMusicID = m_pXA->MusicLoadSong(_T("resource/sounds/Foo Fighters- The Pretender.xwm"));
	m_pLM = CLevelManager::GetInstance();
	m_pLM->LoadLevels();

	m_nSfxID = m_pXA->SFXLoadSound(_T("resource/sounds/UnitDeath.wav"));
	m_nMenuMove = m_pXA->SFXLoadSound(_T("resource/sounds/MenuMove.wav"));
	m_nMenuConfirm = m_pXA->SFXLoadSound(_T("resource/sounds/MenuConfirm.wav"));

	COptionsMenuState::GetInstance()->LoadOptionsXML("Options.xml");

	m_pXA->MusicPlaySong(m_nBackgroundMusicID, true);
	ChangeState( CTitleMenuState::GetInstance() );
	
	m_dwCurrTime = GetTickCount();

	MessageSystem = MessageSystem->GetInstance();
	MessageSystem->InitMessageSystem(&MessgeProc);
}


HINSTANCE CGame::ReturnInsance()
{
	return hGrabInstance;
}

bool CGame::Main( void )
{
	if( Input() == false )
		return false;

	std::vector<CMovingObject*> debugTest;
	debugTest = m_pEntityManager->m_BaseUnits;

	Update();
	Render();
	return true;
}


void CGame::Terminate( void )
{
	//m_pCurrState->Exit();
	COptionsMenuState::GetInstance()->SaveOptionsXML("Options.xml");

	ChangeState( nullptr );

	CLevelManager::GetInstance()->DeleteInstance();

	m_pBF->Shutdown();
	delete m_pBF;
	m_pBF = nullptr;

	m_pParticleManager->DeleteInstance();
	m_pParticleManager = nullptr;
	m_pEntityManager->DeleteInstance();
	m_pEntityManager = nullptr;


	m_pXA->Terminate();
	m_pDI->Terminate();
	m_pD3D->Terminate();
	m_pTM->Terminate();

	m_pD3D			= nullptr;
	m_pDI			= nullptr;
	m_pXA			= nullptr;
	m_pTM			= nullptr;

	m_nScreenWidth	= 1;
	m_nScreenHeight	= 1;
	m_bIsWindowed	= true;
	m_bIsFullscreen = true;

	MessageSystem->ClearMessages();
	MessageSystem->Shutdown();
}


bool CGame::Input( void )
{
	m_pDI->ReadDevices();

	if (m_pDI->KeyDown(DIK_LALT) && m_pDI->KeyPressed(DIK_RETURN))
	{
		ToggleFullScreen();
		return true;
	}
	else if (m_pDI->KeyDown(DIK_LALT) && m_pDI->KeyPressed(DIK_F4))
	{
		return false;
	}
	else
	return m_pCurrState->Input();
}

void CGame::Update( void )
{
	MessageSystem->ProcessMessages();

	m_pXA->Update();

	DWORD dwNow = GetTickCount();
	float fElapsedTime = (dwNow - m_dwCurrTime) / 1000.0f;

	if( fElapsedTime > 0.125f )
		fElapsedTime = 0.125f;

	TestMessageThingTimer += fElapsedTime;
	if( TestMessageThingTimer > 1.0f )
	{
		TestMessageThingBool = false;
		TestMessageThingTimer = 0.0f;
	}

	m_dwCurrTime = dwNow;

	m_pCurrState->Update( fElapsedTime );
}

void CGame::Render( void )
{
	m_pD3D->Clear( D3DCOLOR_XRGB( 0, 0, 0 ) );

	m_pD3D->DeviceBegin();
	m_pD3D->SpriteBegin();

	{
		m_pCurrState->Render();
		if(TestMessageThingBool)
		{
			CBitmapFont* font = GetFont();
			font->Draw(_T("Collision"),300,200,2.0f,D3DCOLOR_ARGB(255,0,0,255));
		}
	}

	m_pD3D->SpriteEnd();
	m_pD3D->DeviceEnd();

	m_pD3D->Present();
}


//***********************************************************
// ChangeState
//	- switch the game's active state
void CGame::ChangeState( CGameState* pNewState )
{
	if( m_pCurrState != nullptr )
		m_pCurrState->Exit();

	m_pCurrState = pNewState;

	if( m_pCurrState != nullptr )
		m_pCurrState->Enter();

	if( m_pCurrState == CSinglePlayerState::GetInstance())
	{
		if(m_pXA->MusicIsSongPlaying(m_nBackgroundMusicID))
			m_pXA->MusicStopSong(m_nBackgroundMusicID);
		else if(m_pXA->MusicIsSongPlaying(CLevelManager::GetInstance()->GetCurrLevel()->GetTeam1()->GetBase()->GetWin()))
			m_pXA->MusicStopSong(CLevelManager::GetInstance()->GetCurrLevel()->GetTeam1()->GetBase()->GetWin());
		else if (CLevelManager::GetInstance()->GetCurrLevel()->m_bBossLevel == false && m_pXA->MusicIsSongPlaying(CLevelManager::GetInstance()->GetCurrLevel()->GetTeam2()->GetBase()->GetWin()))
			m_pXA->MusicStopSong(CLevelManager::GetInstance()->GetCurrLevel()->GetTeam2()->GetBase()->GetWin());
		else if (m_pXA->MusicIsSongPlaying(CLevelManager::GetInstance()->GetCurrLevel()->GetTeam1()->GetBase()->GetLose()))
			m_pXA->MusicStopSong(CLevelManager::GetInstance()->GetCurrLevel()->GetTeam1()->GetBase()->GetLose());
		else if (CLevelManager::GetInstance()->GetCurrLevel()->m_bBossLevel == false && m_pXA->MusicIsSongPlaying(CLevelManager::GetInstance()->GetCurrLevel()->GetTeam2()->GetBase()->GetLose()))
			m_pXA->MusicStopSong(CLevelManager::GetInstance()->GetCurrLevel()->GetTeam2()->GetBase()->GetLose());
		m_nBackgroundMusicID = m_pXA->MusicLoadSong(_T("resource/sounds/Sabrepulse - A Girl I Know.xwm"));
		m_pXA->MusicPlaySong(m_nBackgroundMusicID, true);
	}

	else if( m_pCurrState == CPauseMenuState::GetInstance())
	{
		if(m_pXA->MusicIsSongPlaying(m_nBackgroundMusicID))
			m_pXA->MusicStopSong(m_nBackgroundMusicID);
		else if(m_pXA->MusicIsSongPlaying(CLevelManager::GetInstance()->GetCurrLevel()->GetTeam1()->GetBase()->GetWin()))
			m_pXA->MusicStopSong(CLevelManager::GetInstance()->GetCurrLevel()->GetTeam1()->GetBase()->GetWin());
		else if (CLevelManager::GetInstance()->GetCurrLevel()->m_bBossLevel == false && m_pXA->MusicIsSongPlaying(CLevelManager::GetInstance()->GetCurrLevel()->GetTeam2()->GetBase()->GetWin()))
			m_pXA->MusicStopSong(CLevelManager::GetInstance()->GetCurrLevel()->GetTeam2()->GetBase()->GetWin());
		else if (m_pXA->MusicIsSongPlaying(CLevelManager::GetInstance()->GetCurrLevel()->GetTeam1()->GetBase()->GetLose()))
			m_pXA->MusicStopSong(CLevelManager::GetInstance()->GetCurrLevel()->GetTeam1()->GetBase()->GetLose());
		else if (CLevelManager::GetInstance()->GetCurrLevel()->m_bBossLevel == false && m_pXA->MusicIsSongPlaying(CLevelManager::GetInstance()->GetCurrLevel()->GetTeam2()->GetBase()->GetLose()))
			m_pXA->MusicStopSong(CLevelManager::GetInstance()->GetCurrLevel()->GetTeam2()->GetBase()->GetLose());
		m_nBackgroundMusicID = m_pXA->MusicLoadSong(_T("resource/sounds/Foo Fighters- The Pretender.xwm"));
		m_pXA->MusicPlaySong(m_nBackgroundMusicID, true);
	}
}

int CGame::GetScreenMidPoint(string str, float scale)
{
	CBitmapFont * font = GetFont();
	return (GetScreenWidth()/2) - (font->GetStringWidth(str, scale)/2);
}

void CGame::ToggleFullScreen()
{
	m_bIsFullscreen = !m_bIsFullscreen;
	CSGD_Direct3D::GetInstance()->Resize(GetScreenWidth(),GetScreenHeight(),m_bIsFullscreen);
}

/*static*/ void CGame::MessgeProc( CMessage* pMsg )
{
	switch( pMsg->GetMessageID() )
	{
	case MSG_BASE_MESSAGE:

		break;
	case MSG_CREATE_BULLET:

		break;
	case MSG_UNIT_COLLISION:
		CGame::GetInstance()->TestMessageThingBool = true;
		CGame::GetInstance()->TestMessageThingTimer = 0.0f;
		break;
	case MSG_END_GAME:
		CGame::GetInstance()->ChangeState( CMainMenuState::GetInstance() );
	default:
		break;
	}
}
